<?php

namespace App\Console\Commands;

use App\Models\Common\Common;
use App\Models\Tools\Data;
use App\Models\Tools\Period;
use App\Models\Work;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ExploreOvertime extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:explore_overtime';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '检查投稿过期(待投稿、被拒回)并取消工单';

    protected $applier_arr = [];
    protected $receiver_arr = [];

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $overtimes = Period::getSetting('EXPLORE_UPLOAD_OVERTIME');
        /**
         * 取消待提交状态的超时工单
         */
        try{
            DB::beginTransaction();
            $where = function ($query) use ($overtimes) {
                $query->where('ew.status', '=', Data::DATA_DB_EXPLORE_WORK_STATUS_INIT)
                    ->where('eo.end_date','<=',date('Y-m-d',time()-$overtimes));
            };
            // 查询待提交状态超时的工单信息并X锁
            self::overtime($where);
            DB::commit();
        }catch (\Exception $e){
            Log::emergency(ExploreOvertime::class,['msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
            DB::rollBack();
            return false;
        }

        /**
         * 取消拒回状态的超时工单
         */
        try{
            DB::beginTransaction();
            $where = function ($query) use ($overtimes) {
                $query->where('ew.status', '=', Data::DATA_DB_EXPLORE_WORK_STATUS_REFUSE)
                    ->where('ew.hang_up','<>',1)//挂起的工单暂不处理
                    ->where('ew.updated_at','<=',date('Y-m-d H:i:s',time()-$overtimes));
            };
            self::overtime($where);
            DB::commit();
        }catch (\Exception $e){
            Log::emergency(ExploreOvertime::class,['msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
            DB::rollBack();
            return false;
        }

        /**
         * 发送微信推送
         */
        try {
            // 去重
            $applier_arr = array_unique($this->applier_arr);
            $receiver_arr = array_unique($this->receiver_arr);
            // 查询需要通知人的openid
            $applier_arr = DB::table('lottery_users')->whereIn('we_id',$applier_arr)->pluck('openid')->toArray();
            $receiver_arr = DB::table('lottery_users')->whereIn('we_id',$receiver_arr)->pluck('openid')->toArray();

            //  发送验收拒回微信通知（发送给商家）
            $date = date('Y-m-d H:i:s');
            $data = [
                'first' => '您有一个达人已接单的探店已被取消。',
                'keyword1' => '达人探店',
                'keyword2' => '来飞网',
                'keyword3' => $date,
                'keyword4' => '超时取消',
                'remark' => '探店次数余量已退还到您的账户，您可以再次申请探店，点击查看详情。',
            ];
            //发送通知
            foreach($applier_arr as $openid){
                Common::sendLaifeiMessage($openid,'work_cancel',$data,'/history?tab=1');
            }

            //  发送验收拒回微信通知（发送给达人）
            $data = [
                'first' => '您有探店工单已被取消。',
                'keyword1' => '达人探店',
                'keyword2' => '来飞网',
                'keyword3' => $date,
                'keyword4' => '超时取消',
                'remark' => '点击查看详情',
            ];
            //发送通知
            foreach($receiver_arr as $openid){
                Common::sendLaifeiMessage($openid,'work_cancel',$data,'/talent/history?tab=1');
            }
            if(count($applier_arr)){
                Log::debug('工单超时取消定时任务，推送商家：',$applier_arr);
            }
            if(count($receiver_arr)){
                Log::debug('工单超时取消定时任务，推送达人：',$receiver_arr);
            }
        }catch (\Exception $e){
            Log::error(ExploreOvertime::class,['msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
        }
        return true;
    }

    /**
     * 查询状态超时的工单信息并X锁
     * @param $where
     */
    private function overtime($where)
    {

        $works = DB::table('explore_work as ew')
            ->leftJoin('explore_order as eo','ew.eo_id','=','eo.eo_id')
            ->where($where)
            ->lockForUpdate()
            ->select('ew.work_id','ew.apply_we_id','ew.receiver_we_id','eo.eo_id','eo.channel_id')
            ->get()
            ->toArray();
        $works = json_decode(json_encode($works), true);
        if($works && count($works)){
            Log::debug('订单超时预处理：'.ExploreOvertime::class,$works);
        }
        // 关闭工单
        foreach($works as $work){
            // 优先锁表：订单表和余量表
            $order = Work::exploreOrderAndX($work['eo_id']);
            $remaining = Work::exploreRemainingAndX($work['apply_we_id'],$work['channel_id']);
            // 修改工单状态
            DB::table('explore_work')->where('work_id','=',$work['work_id'])->update([
                'status'=>Data::DATA_DB_EXPLORE_WORK_STATUS_ERROR,
                'error_reason'=>Data::DATA_DB_EXPLORE_WORK_ERROR_REASON_OVERTIME,
            ]);
            // 记录工单日志
            DB::table('explore_work_log')->insert([
                'work_id'=>$work['work_id'],
                'action'=>Data::DATA_DB_EXPLORE_WORK_ACTION_OVERTIME,
                'remark'=>'达人投稿超时',
            ]);
            // 修改订单状态
            Work::workCancelToOrder($order);
            // 修改发单者剩余数量并记录日志
            Work::workCancelToRemaining($remaining);
            // 记录到需要通知人
            $this->applier_arr[] = $work['apply_we_id'];
            $this->receiver_arr[] = $work['receiver_we_id'];
        }

    }
}
